//
// Created by root on 2022/7/18.
//
#include <stdio.h>
#include <string.h>
#include "nginx.h"
#include "ngx_hash.h"
#include "ngx_string.h"
#include "ngx_config.h"
#include "ngx_conf_file.h"
#include "ngx_core.h"
#include "ngx_palloc.h"
#define POOL_SIZE 20000

typedef struct twhash
{
    ngx_str_t name;
    char seq;
}TWHash;
typedef struct Test_2
{
    int a ;
    const char *b ;
    ngx_queue_t testq;
} test2;

typedef struct Test_chain
{
    ngx_chain_t  *next;
    ngx_buf_t    *buf;
} test_chain;
void testString(){
    printf("Hello Runoob！ %d \n" ,"hello" );
    ngx_str_t name = ngx_string("hello");
    printf(name.data);

    /**
     * ngx_string中有一些对系统方法的封装
     * ngx_strcmp 比较两个字符串大小
     * ngx_strstr 查找str1中str2的位置
     * ngx_strlen 字符串长度
     */
    size_t len = strlen("helloworld");

    char men[] = "helloeshin";
    //将字符串开头两个位置设置为f
    ngx_memset(men,'f',2);
    //开头五个位置设置为0;
    ngx_memzero(men,5);

    char src[] = "fffff";
    char dest[] = "helloeshin";
    //拷贝src到dest的开头几位
    ngx_memcpy(dest,src,strlen(src));
    char src1[] = "00000";
    //拷贝后并移动指针
    char *pos = ngx_cpymem(dest,src1,strlen(src1));
    //拷贝到上面移动指针后的位置。
    char *pos1 = ngx_cpymem(pos,src,strlen(src));

}
void testPalloc(){

    printf("Hello Runoob！ %d \n" , sizeof(unsigned long) );

    ngx_pool_t * pool = ngx_create_pool(POOL_SIZE,NULL);//向操作系统申请固定大小内存，POOL指向连续内存的首地址,除去pool结构体占用的内存，剩余作为data区的内存。
    void *mem1 = ngx_palloc(pool, sizeof(test2));//data区里开辟test2结构体大小的内存，从pool后的首地址，data区的首地址开始
    void *mem2 = ngx_palloc(pool,sizeof(test2));
    void *mem3 = ngx_palloc(pool,1918);
    test2 *test;
    test = mem1;
    test->a = 15;
    test->b = 32;

    void *mem4 = ngx_palloc(pool, 5000);
    void *mem5 = ngx_palloc(pool, 5000);

    ngx_destroy_pool(pool);
}

void testArray(){


    ngx_pool_t * pool = ngx_create_pool(POOL_SIZE,NULL);
    ngx_array_t *arr = ngx_array_create(pool, 2, sizeof(test2));

    test2 *test0;
    test2 *test1;
    test2 *test00;

    void *e0 = ngx_array_push(arr);
    test0 = e0;
    test0->a=12;
    test0->b=21;
    void *e1 = ngx_array_push(arr);
    void *e2 = ngx_array_push(arr);

    test1 = e1;
    test1->a = 2;
    test1->b = 3;

    void *elist = ngx_array_push_n(arr, 3);

    test00 = arr->elts;
    printf("a: %d,b: %d \n",test00[0].a,test00[0].b);
    printf("a: %d,b: %d \n",test00[1].a,test00[1].b);
    printf("a: %d,b: %d \n",test00[5].a,test00[5].b);

    ngx_array_destroy(arr);

    ngx_array_t *arr1 = ngx_array_create(pool, 2, 5000);
    ngx_array_destroy(arr1);
}

void testList(){

    test2 *test00;
    ngx_pool_t * pool = ngx_create_pool(POOL_SIZE,NULL);
    ngx_list_t *list = ngx_list_create(pool, 2, sizeof(test2));
    void *e0 = ngx_list_push(list);
    void *e1 = ngx_list_push(list);
    void *e2 = ngx_list_push(list);
    void *e3 = ngx_list_push(list);
    void *e4 = ngx_list_push(list);
    void *e5 = ngx_list_push(list);

    test2 *test0 = e0;
    test0->a=12;
    test0->b=21;

    test2 *test2 = e2;
    test2->a = 2;
    test2->b = 3;


    test00 = list->part.elts;//一个part两个元素，多个part形成list
    printf("a: %d,b: %d \n",test00[0].a,test00[0].b);
    printf("a: %d,b: %d \n",test00[1].a,test00[1].b);
    printf("a: %d,b: %d \n",test00[2].a,test00[2].b);//越界非正常结果

    test00 = list->part.next->elts;
    printf("a: %d,b: %d \n",test00[0].a,test00[0].b);
    printf("a: %d,b: %d \n",test00[1].a,test00[1].b);
    printf("a: %d,b: %d \n",test00[2].a,test00[2].b);//越界非正常结果
}

void testqueue(){
    ngx_queue_t queue;
    ngx_queue_init(&queue);
    test2 t1,t2,t3,t4;
    t1.a = 2;
    t1.b = 3;
    ngx_queue_insert_head(&queue,&t1.testq);
    ngx_queue_insert_head(&queue,&t2.testq);
    ngx_queue_insert_tail(&queue,&t3.testq);

    ngx_queue_t queue2;
    ngx_queue_init(&queue2);
    ngx_queue_insert_head(&queue2,&t4.testq);
    //可两个queue合并
    ngx_queue_add(&queue,&queue2);
//
    int i=0;
    ngx_queue_t *q = ngx_queue_head(&queue);
    ngx_queue_t *start = q;
    while(start != q->next){
        i++;
        printf("current:%02x, pre :%02x,next :%02x \n",q,q->prev,q->next);
        q = ngx_queue_next(q);

        if(i>6)break;
    }
    printf("current:%02x, pre :%02x,next :%02x \n",q,q->prev,q->next);

    while(!ngx_queue_empty(&queue)){
        ngx_queue_t *q = ngx_queue_last(&queue);
        test2 *temp = ngx_queue_data(q, test2, testq);
        printf("point:%02x, temp_pos :%02x,a: %d,b: %d \n",q,temp,temp->a,temp->b);
//        printf("current:%02x, pre :%02x,next :%02x \n",q,q->prev,q->next);
        ngx_queue_remove(&temp->testq);
    }
}
void testBuf(){
    printf("size of buf struct: %d \n" , sizeof(ngx_chain_t) );
    printf("offset of buf in struct chain: %d \n" , offsetof(ngx_chain_t, next) );
    printf("offset of buf in struct chain: %d \n" , offsetof(test_chain , buf) );
    printf("offset of buf in struct chain: %d \n" , offsetof(test2 , b) );
    printf("offset of buf in struct chain: %d \n" , offsetof(test2 , testq) );
    ngx_pool_t * pool = ngx_create_pool(POOL_SIZE,NULL);
    ngx_buf_t *buf1 = ngx_create_temp_buf(pool, 64);
    ngx_buf_t *buf2 = ngx_create_temp_buf(pool, 1980);
    ngx_buf_t *buf3 = ngx_create_temp_buf(pool, 64);
    ngx_buf_t *buf4 = ngx_create_temp_buf(pool, 1980);
    ngx_buf_t *buf6 = ngx_create_temp_buf(pool, 64);
    ngx_buf_t *buf7 = ngx_create_temp_buf(pool, 1980);

    ngx_chain_t *cl = ngx_alloc_chain_link(pool);
    cl->buf = buf1;
    ngx_chain_t *cl2 = ngx_alloc_chain_link(pool);
    cl2->buf = buf2;
    cl->next = cl2;
    ngx_chain_t *cl3= ngx_alloc_chain_link(pool);
    cl3->buf = buf3;
    ngx_chain_t *cl4= ngx_alloc_chain_link(pool);
    cl4->buf = buf4;
    cl3->next = cl4;
    char src[] = "eshin";
//    buf4->last = ngx_cpymem(buf4->last, src,sizeof(src) );
    //src最后一位是0；
    buf4->last = ngx_cpymem(buf4->last, src,sizeof(src)-1 );
    char dest[] = "xxxxx is handsome";
    ngx_memcpy(dest,buf4->pos,buf4->last - buf4->pos);
    /**
     * 当未处理位置pos，与空余空间首地址相同，表示buf内没有未处理数据，
     * 当update_chain时，该buf的chain节点如果在busy链表，将被放到free链表
     */
//    buf4->pos = buf4->last;
    //将cl3中的每个节点拷贝到cl中
//    ngx_chain_add_copy(pool,&cl,cl3);
    //获取cl链表中首chain节点，cl中为null时，通过pool创建0
//    ngx_chain_t *cl5 = ngx_chain_get_free_buf(pool,&cl);

    //将cl赋值给pool的chain，free时，将cl5头插入到chain中
//    pool->chain = cl;
//    ngx_free_chain(pool,cl5);

    ngx_chain_t *cl6 = ngx_alloc_chain_link(pool);
    cl6->buf = buf6;
    ngx_chain_t *cl7 = ngx_alloc_chain_link(pool);
    cl7->buf = buf7;
    cl6->next = cl7;
    ngx_chain_update_chains(pool,&cl,&cl3,&cl6,cl->buf->tag);

}
void testHash(){

    //demo中没有其他位置在启动时设置缓存行大小，此处调用cpuinfo()设置缓存行
    //在后面元素和bucket内存对齐时需要用到缓存行
    ngx_cpuinfo();
    u_short *test = test = ngx_alloc(4 * sizeof(u_short), NULL);;
    test[0] = 58;
    test[1] = 23;
    test[2] = 121;
    test[3] = 140;
    int a = 0;
    for( a = 0; a<4;a++){
        printf("test: %d \n" , test[a]);
        test[a] = (u_short) (ngx_align(test[a], ngx_cacheline_size));
        printf("test: %d \n" , test[a]);
    }

    ngx_pool_t * pool = ngx_create_pool(POOL_SIZE,NULL);
    ngx_array_t *arr = ngx_array_create(pool, 32, sizeof(ngx_hash_key_t));

    ngx_hash_keys_arrays_t haArr;
    ngx_memzero(&haArr, sizeof(ngx_hash_keys_arrays_t));
    haArr.temp_pool = pool;
    ngx_hash_keys_array_init(&haArr,NGX_HASH_LARGE_ASIZE);
    printf("size of ngx_hash_elt_t: %d \n" , sizeof(ngx_hash_elt_t) );
    printf("size of ngx_hash_elt_t: %d \n" , sizeof(ngx_hash_elt_t *) );
    printf("size of ngx_hash_key_t: %d \n" , sizeof(ngx_hash_key_t) );
    printf("size of u_short: %d \n" , sizeof(u_short) );
    printf("size of void*: %d \n" , sizeof(void*) );
    printf("size of char: %d \n" , sizeof(u_char) );



    test2 value[5];
    ngx_str_t key0 = ngx_string("bbbbb-key");
    ngx_str_t key1 = ngx_string("aaaaa-key");
    ngx_str_t key2 = ngx_string("ccccc-key");
    ngx_str_t key3 = ngx_string("ggggg-key");
    ngx_str_t key4 = ngx_string("kkkkk-key");

    ngx_uint_t       i;
    for(i = 0;i<5;i++){
        value[i].a = i;
        value[i].b = i*i;
    }

    ngx_hash_init_t *hash;
    hash = ngx_palloc(pool, sizeof(ngx_hash_init_t));
    hash->pool = pool;
    hash->name = "test_2_hash";
    hash->key = ngx_hash_key;
    hash->max_size = 128;
    hash->bucket_size = 64/*sizeof(test2) *8*/;

    ngx_hash_add_key(&haArr,&key0,&value[0],NGX_HASH_READONLY_KEY);
    ngx_hash_add_key(&haArr,&key1,&value[1],NGX_HASH_READONLY_KEY);
    ngx_hash_add_key(&haArr,&key2,&value[2],NGX_HASH_READONLY_KEY);
    ngx_hash_add_key(&haArr,&key3,&value[3],NGX_HASH_READONLY_KEY);
    ngx_hash_add_key(&haArr,&key4,&value[4],NGX_HASH_READONLY_KEY);

    int testsize = hash->bucket_size / (2 * sizeof(void *));

    ngx_hash_key_t *names = haArr.keys.elts;
    test2 *value00 = names[0].value;
    test2 *value01 = names[1].value;
    ngx_hash_init(hash,haArr.keys.elts,haArr.keys.nelts);

    test2 *node = ngx_hash_find(hash->hash, names[2].key_hash, key2.data, key2.len);


}
void testHashWC(){
    ngx_cpuinfo();

    u_char a[10] = "hElLo";
    u_char b[10] = "";
    u_char *c = a;
    u_char *d = b;
    int n = ngx_strlen(a);
    while (n--) {
        u_char e = *c;
        *d = ngx_tolower(e);
        c++;
        d++;
    }
    ngx_strlow(b,a,3);
//    每个地址对应8bit的内存空间（最小内存单元，1字节）
//    在64位系统中，内存对齐8字节（跨8个地址），对齐后的相邻指针相差8，因此指针二进制的后三位为0（32位系统，后两位为0）；
//    因此获取的指针地址都是8的倍数
    void *ptra = (void *) ((uintptr_t) a );
    void *ptr = (void *) ((uintptr_t) a | 1);
    void *ptr1 = (void *) ((uintptr_t) a | 2);
    void *ptr2 = (void *) ((uintptr_t) a | 3);

    ngx_pool_t * pool = ngx_create_pool(POOL_SIZE,NULL);

    ngx_hash_keys_arrays_t haArr;
    ngx_memzero(&haArr, sizeof(ngx_hash_keys_arrays_t));
    haArr.temp_pool = pool;
    ngx_hash_keys_array_init(&haArr,NGX_HASH_LARGE_ASIZE);
    test2 value[6];

//    ngx_str_t *key0 = ngx_pcalloc(pool, sizeof(ngx_str_t));
//    key0->data = "*.com.cn"; //ngx_strlow不能改变常量，因此data的值不能是常量
//    key0->len = strlen("*.com.cn");
    ngx_str_t key0 = ngx_string("*.com.cn");
    key0.data = ngx_pcalloc(pool, key0.len);
    ngx_memcpy(key0.data,"*.com.cn",key0.len);

    ngx_str_t key1 = ngx_string("*.a.com.cn");
    key1.data = ngx_pcalloc(pool, key1.len);
    ngx_memcpy(key1.data,"*.a.com.cn",key1.len);

    ngx_str_t key2 = ngx_string(".b.com.cn");
    key2.data = ngx_pcalloc(pool, key2.len);
    ngx_memcpy(key2.data,".b.com.cn",key2.len);

    ngx_str_t key3 = ngx_string("cn.org.*");
    key3.data = ngx_pcalloc(pool, key3.len);
    ngx_memcpy(key3.data,"cn.org.*",key3.len);

    ngx_str_t key4 = ngx_string("*.test.cc");
    key4.data = ngx_pcalloc(pool, key4.len);
    ngx_memcpy(key4.data,"*.test.cc",key4.len);

    ngx_str_t key5 = ngx_string(".com.cn");
    key5.data = ngx_pcalloc(pool, key5.len);
    ngx_memcpy(key5.data,".com.cn",key5.len);

    ngx_str_t key6 = ngx_string("*.c.com.cn");
    key6.data = ngx_pcalloc(pool, key6.len);
    ngx_memcpy(key6.data,"*.c.com.cn",key6.len);

    ngx_uint_t       i;
    for(i = 0;i<6;i++){
        value[i].a = i;
        value[i].b = i*i;
    }

    ngx_hash_init_t *hash;
    hash = ngx_palloc(pool, sizeof(ngx_hash_init_t));
    hash->pool = pool;
    hash->temp_pool = pool;
    hash->name = "test_2_hash";
    hash->key = ngx_hash_key;
    hash->max_size = 128;
    hash->bucket_size = 64/*sizeof(test2) *8*/;

    ngx_hash_add_key(&haArr,&key0,&value[0],NGX_HASH_WILDCARD_KEY);
    //*.com.cn与.com.cn在dns_wc_head_hash中都是com.cn。因此这里.com.cn不能添加
    ngx_hash_add_key(&haArr,&key5,&value[5],NGX_HASH_WILDCARD_KEY);
    ngx_hash_add_key(&haArr,&key1,&value[1],NGX_HASH_WILDCARD_KEY);
    ngx_hash_add_key(&haArr,&key2,&value[2],NGX_HASH_WILDCARD_KEY);
    ngx_hash_add_key(&haArr,&key3,&value[3],NGX_HASH_WILDCARD_KEY);
    ngx_hash_add_key(&haArr,&key4,&value[4],NGX_HASH_WILDCARD_KEY);
    ngx_hash_add_key(&haArr,&key6,&value[6],NGX_HASH_WILDCARD_KEY);


    int e = 0;
    ngx_hash_key_t *elt = haArr.dns_wc_head.elts;
    for(e;e<haArr.dns_wc_head.nelts;e++){
        printf("after comvert %s \n" ,elt[e].key.data );
    }
    int h=0;
    for(h;h<128;h++){
        int j=0;
        ngx_array_t hh = haArr.dns_wc_head_hash[h];
        ngx_str_t *elth = hh.elts;
        for(j=0;j<hh.nelts;j++){
            char dest[] = "             ";
            //拷贝src到dest的开头几位
            ngx_memcpy(dest,elth[j].data,elth[j].len);
            printf("after comvert hashkey %s \n" ,dest);
        }
    }

    ngx_hash_key_t *names = haArr.dns_wc_head.elts;
    test2 *value00 = names[0].value;
    test2 *value01 = names[1].value;
    ngx_hash_wildcard_init(hash,haArr.dns_wc_head.elts,haArr.dns_wc_head.nelts);

    ngx_str_t test_0 = ngx_string("e.com.cn");
    test2 *node = ngx_hash_find_wc_head(hash->hash,test_0.data,test_0.len);

    ngx_str_t test_1 = ngx_string("a.a.com.cn");
    test2 *node1 = ngx_hash_find_wc_head(hash->hash,test_1.data,test_1.len);

    ngx_str_t test_2 = ngx_string(".com.cn");
    test2 *node2 = ngx_hash_find_wc_head(hash->hash,test_2.data,test_2.len);
//    ngx_hash_wildcard_init(hash,haArr.dns_wc_tail.elts,haArr.dns_wc_tail.nelts);





}

void testOpenFileCache(){

    /**
     *    需先对时间初始化，否则now = ngx_time();这句会报错
     */
    ngx_time_init();

    ngx_open_file_info_t          of;
    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
    of.read_ahead = 128;
//    of.directio = clcf->directio;
    of.valid = 30;
//    of.min_uses = clcf->open_file_cache_min_uses;
//    of.test_only = 1;
    of.errors = 0;
//    of.events = clcf->open_file_cache_events;
    ngx_pool_t * pool = ngx_create_pool(POOL_SIZE,NULL);
    ngx_open_file_cache_t  *open_file_cache = ngx_open_file_cache_init(pool, 32, 60);
    ngx_str_t name = ngx_string("/root/a.txt");
//    ngx_open_cached_file(NULL,&name,&of,pool);
    ngx_open_cached_file(open_file_cache,&name,&of,pool);
    //第二次访问，通过cache访问
    ngx_open_cached_file(open_file_cache,&name,&of,pool);
}

void testEvent(){


    struct epoll_event  ee;
    struct epoll_event  ee1;

    int ep = epoll_create(512);
    int notify_fd = eventfd(0, 0);
    ee.events = EPOLLIN|EPOLLET;
    ee1.events = EPOLLIN|EPOLLET;
    int re = epoll_ctl(ep, EPOLL_CTL_ADD, notify_fd, &ee);
    int re1 = epoll_ctl(ep, EPOLL_CTL_MOD, notify_fd, &ee1);
}
